#include "myrpcapplication.h"
#include "user.pb.h"
#include "myrpccontroller.h"
#include "myrpclogger.h"
#include "myrpcchannel.h"
#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
#include <string>


void send_request(int thread_id, std::atomic<int>& successs_count, std::atomic<int>& fail_count) {
    
    user::UserServiceRPC_Stub stub(new MyRPCChannel(false));

    // 构造请求参数
    user::LoginRequest request;
    request.set_name("zhangsan");
    request.set_pwd("123456");

    // 构造出response和controller对象
    user::LoginResponse response;
    MyRPCController controller;
    // 发起Login函数调用
    // Login函数内部调用的是channel实例的CallMethod函数
    stub.Login(&controller, &request, &response, nullptr);

    if (controller.Failed()) {
        // 请求失败了则打印出错误信息
        std::cout << controller.ErrorText() << std::endl;
    } else {
        // 说明请求成功了
        if (0 == response.result().errcode()) {
            // 说明登录成功了
            std::cout << "rpc login success: " << response.success() << "\n";
            successs_count++;
        } else {
            // 说明登录失败了
            std::cout << "rpc login failed: " << response.result().errmsg() << "\n";
            fail_count++;
        }
    }
}


int main(int argc, char** argv) {
    // 初始化application
    MyRPCApplication::init(argc, argv);
    MyRPCLooger logger("MyRPC");

    const int thread_count = 1000; // 1k的并发线程数
    const int requests_pre_thread = 10; // 每个线程发送的请求数

    std::vector<std::thread> threads;
    std::atomic<int> success_count(0);
    std::atomic<int> fail_count(0);

    // 记录开始时间
    auto start_time = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < thread_count; ++i) {
        threads.emplace_back([argc, argv, i, &success_count, &fail_count, requests_pre_thread](){
            for (int j = 0; j < requests_pre_thread; ++j) {
                send_request(i, success_count, fail_count);
            }
        });
    }

    // 等待所有子线程全部结束后，再继续执行
    for (auto &t : threads) {
        t.join();
    }
    // 记录结束时间
    auto end_time = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = end_time - start_time;

    logger.Info("Total requests: " + std::to_string(thread_count * requests_pre_thread));
    logger.Info("Success count:  " + std::to_string(success_count));
    logger.Info("Fail count: " + std::to_string(fail_count));
    logger.Info("Elapsed time: " + std::to_string(elapsed.count()) + "seconds");
    logger.Info("QPS: " + std::to_string((thread_count * requests_pre_thread) / elapsed.count()));
    return 0;
}